#include "baidu_speech_client.h"
#include <QUrlQuery>
#include <QHttpMultiPart>
#include <QHttpPart>
#include <QJsonArray>
#include <QDateTime>

const QString BaiduSpeechClient::TOKEN_URL = "https://aip.baidubce.com/oauth/2.0/token";
const QString BaiduSpeechClient::RECOGNITION_URL = "https://vop.baidu.com/pro_api";

BaiduSpeechClient::BaiduSpeechClient(QObject *parent)
    : QObject(parent)
    , m_networkManager(new QNetworkAccessManager(this))
    , m_currentReply(nullptr)
    , m_initialized(false)
    , m_tokenExpireTime(0)
{
}

BaiduSpeechClient::~BaiduSpeechClient()
{
}

bool BaiduSpeechClient::initialize(const QString &appId, const QString &apiKey, const QString &secretKey)
{
    m_appId = appId;
    m_apiKey = apiKey;
    m_secretKey = secretKey;
    
    qDebug() << "初始化百度语音识别客户端...";
    qDebug() << "AppID:" << m_appId;
    qDebug() << "API Key:" << m_apiKey.left(8) + "...";
    
    // 请求访问令牌
    requestAccessToken();
    
    m_initialized = true;
    return true;
}

void BaiduSpeechClient::requestAccessToken()
{
    QUrl url(TOKEN_URL);
    QUrlQuery query;
    query.addQueryItem("grant_type", "client_credentials");
    query.addQueryItem("client_id", m_apiKey);
    query.addQueryItem("client_secret", m_secretKey);
    url.setQuery(query);
    
    QNetworkRequest request(url);
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
    request.setHeader(QNetworkRequest::UserAgentHeader, "Qt-BaiduSpeech/1.0");
    
    // 设置超时时间为5秒
    request.setTransferTimeout(5000);
    
    qDebug() << "请求访问令牌:" << url.toString();
    
    QNetworkReply *reply = m_networkManager->post(request, QByteArray());
    connect(reply, &QNetworkReply::finished, this, &BaiduSpeechClient::onTokenReplyFinished);
}

QString BaiduSpeechClient::getAccessToken()
{
    qint64 currentTime = QDateTime::currentSecsSinceEpoch();
    
    // 如果令牌即将过期（提前5分钟刷新）
    if (currentTime >= m_tokenExpireTime - 300) {
        qDebug() << "访问令牌即将过期，重新请求...";
        requestAccessToken();
        return QString(); // 返回空字符串，等待新令牌
    }
    
    return m_accessToken;
}

void BaiduSpeechClient::onTokenReplyFinished()
{
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
    if (!reply) return;
    
    reply->deleteLater();
    
    if (reply->error() != QNetworkReply::NoError) {
        qWarning() << "获取访问令牌失败:" << reply->errorString();
        emit recognitionError("获取访问令牌失败: " + reply->errorString());
        return;
    }
    
    QByteArray data = reply->readAll();
    QJsonDocument doc = QJsonDocument::fromJson(data);
    QJsonObject obj = doc.object();
    
    if (obj.contains("access_token")) {
        m_accessToken = obj["access_token"].toString();
        int expiresIn = obj["expires_in"].toInt();
        m_tokenExpireTime = QDateTime::currentSecsSinceEpoch() + expiresIn;
        
        qDebug() << "成功获取访问令牌，有效期:" << expiresIn << "秒";
    } else {
        QString error = obj["error_description"].toString();
        qWarning() << "获取访问令牌失败:" << error;
        emit recognitionError("获取访问令牌失败: " + error);
    }
}

void BaiduSpeechClient::recognizeAudio(const QByteArray &audioData, const QString &format, int rate)
{
    if (!m_initialized) {
        emit recognitionError("客户端未初始化");
        return;
    }
    
    QString token = getAccessToken();
    if (token.isEmpty()) {
        emit recognitionError("访问令牌无效，请稍后重试");
        return;
    }
    
    // 检查音频数据大小（百度API限制为60秒，约1.2MB）
    if (audioData.size() > 1200000) {
        emit recognitionError("音频数据过大，请缩短录音时间");
        return;
    }
    
    if (audioData.size() < 1000) {
        emit recognitionError("音频数据过小，请重新录音");
        return;
    }
    
    qDebug() << "开始语音识别，音频大小:" << audioData.size() << "字节，格式:" << format << "，采样率:" << rate;
    
    // 构建请求（按照百度官方示例格式）
    QUrl url(RECOGNITION_URL);
    
    // 构建JSON请求体（按照官方示例）
    QJsonObject requestObj;
    requestObj["format"] = format;
    requestObj["rate"] = rate;
    requestObj["channel"] = 1;
    requestObj["cuid"] = "qt_speech_client";
    requestObj["dev_pid"] = 80001; // 极速版普通话识别（按照官方示例）
    requestObj["len"] = audioData.size();
    requestObj["token"] = token;
    requestObj["speech"] = QString(audioData.toBase64());
    
    QJsonDocument requestDoc(requestObj);
    QByteArray requestData = requestDoc.toJson(QJsonDocument::Compact);
    
    QNetworkRequest request(url);
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
    request.setHeader(QNetworkRequest::UserAgentHeader, "Qt-BaiduSpeech/1.0");
    
    // 设置超时时间为10秒
    request.setTransferTimeout(10000);
    
    qDebug() << "发送语音识别请求到:" << url.toString();
    
    // 如果有正在进行的请求，先取消
    if (m_currentReply) {
        m_currentReply->abort();
        m_currentReply->deleteLater();
        m_currentReply = nullptr;
    }
    
    m_currentReply = m_networkManager->post(request, requestData);
    connect(m_currentReply, &QNetworkReply::finished, this, &BaiduSpeechClient::onRecognitionReplyFinished);
}

void BaiduSpeechClient::onRecognitionReplyFinished()
{
    QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
    if (!reply) return;
    
    // 清除当前请求引用
    if (reply == m_currentReply) {
        m_currentReply = nullptr;
    }
    
    reply->deleteLater();
    
    if (reply->error() != QNetworkReply::NoError) {
        qWarning() << "语音识别请求失败:" << reply->errorString();
        emit recognitionError("网络请求失败: " + reply->errorString());
        return;
    }
    
    QByteArray data = reply->readAll();
    QJsonDocument doc = QJsonDocument::fromJson(data);
    QJsonObject obj = doc.object();
    
    qDebug() << "收到语音识别响应:" << doc.toJson(QJsonDocument::Compact);
    
    int errNo = obj["err_no"].toInt();
    if (errNo == 0) {
        // 识别成功
        QJsonArray resultArray = obj["result"].toArray();
        if (!resultArray.isEmpty()) {
            QString result = resultArray[0].toString();
            qDebug() << "语音识别成功:" << result;
            emit recognitionResult(result);
        } else {
            emit recognitionError("识别结果为空");
        }
    } else {
        // 识别失败
        QString errMsg = obj["err_msg"].toString();
        qWarning() << "语音识别失败，错误码:" << errNo << "错误信息:" << errMsg;
        emit recognitionError(QString("识别失败[%1]: %2").arg(errNo).arg(errMsg));
    }
}

void BaiduSpeechClient::stopRecognition()
{
    qDebug() << "停止百度语音识别";
    
    // 取消正在进行的识别请求
    if (m_currentReply) {
        qDebug() << "取消正在进行的识别请求";
        m_currentReply->abort();
        m_currentReply->deleteLater();
        m_currentReply = nullptr;
    }
} 